package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.BizStatusEnum;
import cc.rengu.igas.momp.common.enums.McTypeEnum;
import cc.rengu.igas.momp.common.enums.RespCodeEnum;
import cc.rengu.igas.momp.common.util.MompAmountUtil;
import cc.rengu.igas.momp.facade.bean.PaymentReturnOrderMchntFeeDiscountInfoBean;
import cc.rengu.igas.momp.facade.request.ComboMchntFeeDiscountTrialRefundRequest;
import cc.rengu.igas.momp.facade.response.ComboMchntFeeDiscountTrialRefundResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DbsUtil;
import cc.rengu.oltp.utility.util.XmlConfigUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liujinan
 * @version 1.0.0
 * @date 2020/5/9
 * @description 手续费优惠回退试算
 */
public class ComboMchntFeeDiscountTrialRefundService extends RadpService {
    private BigDecimal zero = BigDecimal.ZERO;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest = new ComboMchntFeeDiscountTrialRefundRequest();
            ConvertUtil.convertOutput(comboMchntFeeDiscountTrialRefundRequest);

            ComboMchntFeeDiscountTrialRefundResponse comboMchntFeeDiscountTrialRefundResponse = new ComboMchntFeeDiscountTrialRefundResponse();
            comboMchntFeeDiscountTrialRefundResponse.setHeader(comboMchntFeeDiscountTrialRefundRequest.getHeader());
            BizResponse<ComboMchntFeeDiscountTrialRefundResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboMchntFeeDiscountTrialRefundResponse);

            //接口请求报文检查
            checkRequestMessage(comboMchntFeeDiscountTrialRefundRequest);

            // 调用处理流程
            BizResponse<ComboMchntFeeDiscountTrialRefundResponse> bizResponseNew = comboMchntFeeDiscountTrialRefund(xmlTreeUtil, comboMchntFeeDiscountTrialRefundRequest, comboMchntFeeDiscountTrialRefundResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());
        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 手续费优惠回退试算
     *
     * @param comboMchntFeeDiscountTrialRefundRequest
     * @param comboMchntFeeDiscountTrialRefundResponse
     * @param xmlTreeUtil                              内部XML树
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private BizResponse<ComboMchntFeeDiscountTrialRefundResponse> comboMchntFeeDiscountTrialRefund(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest, ComboMchntFeeDiscountTrialRefundResponse comboMchntFeeDiscountTrialRefundResponse)
            throws Exception {

        BizResponse<ComboMchntFeeDiscountTrialRefundResponse> bizResponse = new BizResponse<>();
        rglog.debug("交易类型 TXN_NUM = {}", comboMchntFeeDiscountTrialRefundRequest.getHeader().getTxnNum());
        String instId = comboMchntFeeDiscountTrialRefundRequest.getHeader().getInstId();
        String origTxnDate = comboMchntFeeDiscountTrialRefundRequest.getOrigTxnDate();
        String origTraceNo = comboMchntFeeDiscountTrialRefundRequest.getOrigTraceNo();

        //开启数据库事务
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        try {
            //查询原交易订单流水信息
            TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
            rglog.info("查询原交易流水<{}>开始...", origTraceNo);
            TMTxnOrder oriTMTxnOrder = tmTxnOrderMapper.selectFeeDiscountOriginalTransactionOrderInfo(instId, origTxnDate, origTraceNo);
            if (null == oriTMTxnOrder) {
                rglog.error("机构<{}>在<{}>的原交易订单流水信息<{}>查询失败，未查询到记录", instId, origTxnDate, origTraceNo);
            }

            //查询原交易订单明细信息
            TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
            rglog.info("查询原交易订单明细信息<{}>开始...", origTraceNo);
            List<TMTxnOrderDet> oriTMTxnOrderDetList = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTxnDate, origTraceNo);
            if (null == oriTMTxnOrderDetList || oriTMTxnOrderDetList.isEmpty()) {
                rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>查询失败，未查询到明细记录", instId, origTxnDate, origTraceNo);
            }

            if (null == oriTMTxnOrder || null == oriTMTxnOrderDetList || oriTMTxnOrderDetList.isEmpty()) {
                rglog.info("没有查询到交易流水或交易流水明细记录，不继续进行试算，直接返回响应...");
                //请求上送订单信息
                List<PaymentReturnOrderMchntFeeDiscountInfoBean> feeReturnOrderList = comboMchntFeeDiscountTrialRefundRequest.getFeeReturnOrderList();

                for (PaymentReturnOrderMchntFeeDiscountInfoBean paymentReturnOrderMchntFeeDiscountInfoBean : feeReturnOrderList) {
                    paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
                    paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeActual(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeReceivable());
                    paymentReturnOrderMchntFeeDiscountInfoBean.setMchntFeeDiscountMethod(CommonConstant.ZERO_COMMON_CONSTANT);
                }
                comboMchntFeeDiscountTrialRefundResponse.setFeeReturnOrderList(feeReturnOrderList);
            } else {
                //处理商户手续费优惠回退试算
                processMchntFeeDiscountRefundTrialProcedure(comboMchntFeeDiscountTrialRefundRequest, oriTMTxnOrder, oriTMTxnOrderDetList, comboMchntFeeDiscountTrialRefundResponse);
            }
            dbsUtil.dbsEndTransaction(true);
        } catch (Exception e) {
            rglog.error("商户手续费优惠回退试算失败!所有数据库操作回滚!");
            //事务处理失败关闭数据库事务
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.FAILED_TO_REFUND_TRIAL.getRespCode(), RespCodeEnum.FAILED_TO_REFUND_TRIAL.getRespDesc());
        }

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        comboMchntFeeDiscountTrialRefundResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        comboMchntFeeDiscountTrialRefundResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(comboMchntFeeDiscountTrialRefundResponse);

        return bizResponse;
    }

    /**
     * 商户手续费优惠回退试算
     *
     * @param comboMchntFeeDiscountTrialRefundRequest 请求报文提
     * @param oriTMTxnOrderDetList                    订单明细列表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/11 10:24
     */
    private void processMchntFeeDiscountRefundTrialProcedure(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest, TMTxnOrder oriTMTxnOrder,
                                                             List<TMTxnOrderDet> oriTMTxnOrderDetList, ComboMchntFeeDiscountTrialRefundResponse comboMchntFeeDiscountTrialRefundResponse) throws Exception {

        List<PaymentReturnOrderMchntFeeDiscountInfoBean> returnFeeDiscountInfoBeanList = new ArrayList<>();

        for (PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean : comboMchntFeeDiscountTrialRefundRequest.getFeeReturnOrderList()) {
            // 检查上传字段 不能为负数
            checkFeeReturnOrderFieldHasNegativeNumber(feeDiscountInfoBean);

            int returnCode;
            String instId = oriTMTxnOrder.getInstId();
            String transDate = oriTMTxnOrder.getTxnDate();
            String mchntNo = feeDiscountInfoBean.getMchntNo();
            String orderId = oriTMTxnOrder.getOrderId();
            //通过商户号获取原交易明细
            List<TMTxnOrderDet> oriTMTxnOrderDetListMdf = oriTMTxnOrderDetList.stream().filter(item -> ((McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());

            if (!oriTMTxnOrderDetListMdf.isEmpty()) {
                rglog.info("通过商户号获取原交易明细信息<{}> 条.", oriTMTxnOrderDetList.size());
                //判断记录条数
                if (CommonConstant.ONE != oriTMTxnOrderDetListMdf.size()) {
                    //每个合并支付订单应该只有一条记录，有多条说明是异常情况,流程结束
                    rglog.error("机构<{}>在<{}>的商户<{}>的支付订单明细有多条,异常!", oriTMTxnOrder.getInstId(), oriTMTxnOrder.getTxnDate(), feeDiscountInfoBean.getMchntNo());
                    throw new BizException(RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespCode(), RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespDesc());
                }
                //商户手续费优惠回退试算处理流程－逐个订单明细处理
                returnCode = processSingleMchntFeeDiscountRefundTrialProcedure(comboMchntFeeDiscountTrialRefundRequest, feeDiscountInfoBean, oriTMTxnOrder, oriTMTxnOrderDetListMdf.get(CommonConstant.ZERO));

                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的手续费回退试算失败!", instId, transDate, orderId, mchntNo);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                // 未找到对应商户的手续费优惠信息，不处理！
                rglog.error("机构<{}>在<{}>的商户<{}>未参加任何商户手续费优惠类营销活动，不进行优惠回退试算!", instId, transDate, mchntNo);
                feeDiscountInfoBean.setMchntFeeActual(feeDiscountInfoBean.getMchntFeeReceivable());
                feeDiscountInfoBean.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
            }
            //将明细信息添加到List
            returnFeeDiscountInfoBeanList.add(feeDiscountInfoBean);
        }
        //处理完成后插入订单流水
        recordTxnOrder(comboMchntFeeDiscountTrialRefundRequest, oriTMTxnOrder, returnFeeDiscountInfoBeanList);
        //设置返回列表信息
        comboMchntFeeDiscountTrialRefundResponse.setFeeReturnOrderList(returnFeeDiscountInfoBeanList);
    }

    /**
     * 单个商户手续费优惠订单明细回退试算
     *
     * @param feeDiscountInfoBean 接口上送的手续费优惠回退订单信息
     * @param oriTMTxnOrder       订单流水信息
     * @param oriTMTxnOrderDet    原订单明细信息
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/11 19:17
     */
    private int processSingleMchntFeeDiscountRefundTrialProcedure(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest,
                                                                  PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, TMTxnOrder oriTMTxnOrder, TMTxnOrderDet oriTMTxnOrderDet) throws Exception {
        // 通过原订单金额和本次退款订单金额判断是全额退货还是部分退货
        //原手续费优惠流水中relative_data(关联信息)字段中取值
        String relativeData = oriTMTxnOrderDet.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);
        //原商户订单明细金额
        BigDecimal origOrderAmt = new BigDecimal(relativeDataJson.get("orderAmt").toString());

        //本次上送的退款订单金额
        BigDecimal refundOrderAmt = new BigDecimal(feeDiscountInfoBean.getMchntSettleAmt());

        if (CommonConstant.IS_EQUAL_TO == origOrderAmt.compareTo(refundOrderAmt)) {
            //全额退款场景
            fullyMchntFeeDiscountRefundTrial(comboMchntFeeDiscountTrialRefundRequest, feeDiscountInfoBean, oriTMTxnOrder, oriTMTxnOrderDet);
        } else {
            //部分退款场景
            partMchntFeeDiscountRefundTrial(comboMchntFeeDiscountTrialRefundRequest, feeDiscountInfoBean, oriTMTxnOrder, oriTMTxnOrderDet, origOrderAmt, refundOrderAmt);
        }
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 计算部分退款商户，商户应退优惠手续费
     *
     * @param feeDiscountInfoBean 接口上送的手续费优惠回退订单信息
     * @param oriTMTxnOrder       原订单流水信息
     * @param oriTMTxnOrderDet    原订单明细信息
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/4/27 09:58
     */
    private int partMchntFeeDiscountRefundTrial(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest,
                                                PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, TMTxnOrder oriTMTxnOrder,
                                                TMTxnOrderDet oriTMTxnOrderDet, BigDecimal oriMchntSettleAmt, BigDecimal refundMchntSettleAmt) throws Exception {

        String instId = oriTMTxnOrder.getInstId();
        String transDate = oriTMTxnOrder.getTxnDate();
        String mchntNo = oriTMTxnOrderDet.getMchntNo();
        String traceNo = oriTMTxnOrder.getFrontSeqNum();
        //关联信息
        String relativeData = oriTMTxnOrderDet.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

        rglog.info("获取原交易流水<{}>的信息RELATIVE_DATA值开始...", traceNo);
        //原手续费优惠流水中relative_data(关联信息)字段中取值
        //商户手续费优惠类型
        String discountType = relativeDataJson.get("discountType").toString();
        //优惠力度
        BigDecimal discount = new BigDecimal(relativeDataJson.get("discount").toString());
        //商户应收手续费金额
        BigDecimal mchntFeeReceivable = new BigDecimal(relativeDataJson.get("mchntFeeReceivable").toString());
        //商户应收手续费费率
        BigDecimal mchntFeeReceivableRate = BigDecimal.ZERO;
        Object mchntFeeReceivableRateObject = relativeDataJson.get("mchntFeeReceivableRate");
        if (null == mchntFeeReceivableRateObject) {
            //获取原支付交易的源系统标识，迁移数据固定为“SJQY”
            String msgSrcId = oriTMTxnOrder.getMsgSrcId();
            //如果是迁移的数据，没有feeInputMode值正常，迁移数据都为
            if (CommonConstant.SHUJUQIANYI.equals(msgSrcId)) {
                rglog.info("本次退货交易流水<{}> 为老平台迁移数据，原交易订单明细中mchntFeeReceivableRate为空!", traceNo);
            } else {
                //不是迁移数据时，如果字段为空，则原交易存在问题
                rglog.error("本次退货原交易流水<{}> 原交易不是迁移数据，交易订单明细中mchntFeeReceivableRate为空，异常!", oriTMTxnOrder.getFrontSeqNum());
                throw new BizException(RespCodeEnum.FAILED_TO_REFUND_TRIAL.getRespCode(), RespCodeEnum.FAILED_TO_REFUND_TRIAL.getRespDesc());
            }
        } else {
            /* 商户应收手续费费率 */
            mchntFeeReceivableRate = new BigDecimal(mchntFeeReceivableRateObject.toString()).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
        }

        //实收手续费金额
        BigDecimal mchntFeeActual = new BigDecimal(oriTMTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(oriTMTxnOrderDet.getSubsidy()));
        //手续费收取方式,赋默认值“手工输入按比率”
        String feeInputMode = CommonConstant.FEE_MODE_RATE;
        Object feeInputModeObject = relativeDataJson.get("feeInputMode");
        if (null == feeInputModeObject) {
            //获取原支付交易的源系统标识，迁移数据固定为“SJQY”
            String msgSrcId = oriTMTxnOrder.getMsgSrcId();
            //如果是迁移的数据，没有feeInputMode值正常
            if (CommonConstant.SHUJUQIANYI.equals(msgSrcId)) {
                rglog.info("本次退货交易流水<{}> 为老平台迁移数据，原交易订单明细中feeInputMode为空!", traceNo);
            } else {
                //不是迁移数据时，如果字段为空，则原交易存在问题
                rglog.error("本次退货原交易流水<{}> 原交易不是迁移数据，交易订单明细中feeInputMode为空，异常!", oriTMTxnOrder.getFrontSeqNum());
                throw new BizException(RespCodeEnum.FAILED_TO_REFUND_TRIAL.getRespCode(), RespCodeEnum.FAILED_TO_REFUND_TRIAL.getRespDesc());
            }
        } else {
            feeInputMode = feeInputModeObject.toString();
        }

        //接口上送的本次应退手续费
        BigDecimal thisTimeMchntFeeReceivable = new BigDecimal(feeDiscountInfoBean.getMchntFeeReceivable());


        //本次退款记录的,手续费优惠金额,实退手续费金额
        BigDecimal refundmchntFeeDiscount = BigDecimal.ZERO;
        BigDecimal refundMchntFeeActual = BigDecimal.ZERO;

        //剩余消费金额
        BigDecimal residueOrderAmt = BigDecimal.ZERO;
        //剩余消费金额应收手续费
        BigDecimal residueFeeActual = BigDecimal.ZERO;

        //已退货订单总金额
        BigDecimal refundOrderAmtTotal = BigDecimal.ZERO;//本次退货订单金额＋已退货订单总金额
        //累计实退手续费金额
        BigDecimal alredayRefundCharge = BigDecimal.ZERO;

        //1000
        BigDecimal thousand = new BigDecimal(CommonConstant.THOUSAND);

        //获取已退货信息
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        rglog.info("查询法人机构号<{}>的<{}>的流水号<{}>的商户<{}>的退货统计数据开始...", instId, transDate, traceNo, mchntNo);
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, transDate, traceNo, mchntNo);

        if (null == tmStatRefund) {
            rglog.info("未取到退货记录，说明之前未有过退货订单,本次为第一次部分退款!");
            //剩余消费金额 ＝ 原商户清算金额（有可能与原订单明细订单金额相同)－本次退货订单金额(如果商户清算金额存在，则使用的是商户清算金额，不存在使用退款金额字段)
            residueOrderAmt = oriMchntSettleAmt.subtract(refundMchntSettleAmt);
            //累计实退手续费金额
            alredayRefundCharge = BigDecimal.ZERO;
            //已退货订单总金额
            refundOrderAmtTotal = BigDecimal.ZERO;
        } else {
            //剩余消费金额 ＝ 原商户清算金额（有可能与原订单明细订单金额相同)－累计退货订单金额-本次退货订单金额
            residueOrderAmt = oriMchntSettleAmt.subtract(new BigDecimal(tmStatRefund.getRefundOrderAmt())).subtract(refundMchntSettleAmt);
            //累计实退手续费金额
            alredayRefundCharge = new BigDecimal(tmStatRefund.getRefundMchntFee());
            //已退货订单总金额
            refundOrderAmtTotal = new BigDecimal(tmStatRefund.getRefundOrderAmt());
        }
        //本次退货订单金额＋已退货订单总金额 ,用于判断是否是最后一笔退款
        BigDecimal afterOrderAmt = refundMchntSettleAmt.add(refundOrderAmtTotal);

        rglog.info("订单<{}>手续费回退试算加本次共退款金额为<{}>", traceNo, afterOrderAmt);
        if (afterOrderAmt.compareTo(oriMchntSettleAmt) > 0) {
            rglog.error("订单<{}>手续费回退试算失败,总退款金额超过原订单金额!", traceNo);
            throw new BizException(RespCodeEnum.FAILED_TO_REFUND_TRIAL_EXCEED.getRespCode(), RespCodeEnum.FAILED_TO_REFUND_TRIAL_EXCEED.getRespDesc());
        }

        switch (feeInputMode) {
            case CommonConstant.FEE_MODE_LADDER:
                // 使用现有费率
                rglog.error("商户<{}>,手续费收取方式<{}>-使用现有费率,不支持配置费率模板方式的商户手续费优惠计算!!", feeDiscountInfoBean.getMchntNo(), feeInputMode);
                refundmchntFeeDiscount = refundmchntFeeDiscount;
                refundMchntFeeActual = thisTimeMchntFeeReceivable;
                break;
            case CommonConstant.FEE_MODE_RATE:
                // 手工输入按比率
                switch (discountType) {
                    //手续费全免
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-免手续费!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                        refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        break;
                    //费率打折,实收 = 订单金额*应收费率*折扣,优惠=应收-实收
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-费率打折!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(oriMchntSettleAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(mchntFeeReceivableRate).divide(thousand).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    // 固定费率,实收=订单金额*优惠费率,优惠=应收-实收
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-固定费率!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(oriMchntSettleAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(discount).divide(thousand).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-优惠类型异常!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                }
                break;
            // 手工输入按固定金额
            case CommonConstant.FEE_MODE_FIXED_AMT:
                switch (discountType) {
                    // 手续费全免,在最后一次退款中退
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-免手续费!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                        refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        break;
                    //手工输入按固定金额,不支持费率打折或固定费率的优惠方式
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-不可使用费率打折或固定费率的商户手续费优惠方式!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-优惠类型异常!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                }
                break;
            // 手工输入按比率+封顶值
            case CommonConstant.FEE_MODE_RATE_AMT:
                switch (discountType) {
                    //手续费全免
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-免手续费!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        //本次是最后一笔退款
                        refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                        refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        break;
                    //discount_type= 1-费率打折  实收=min(订单金额*费率*折扣,应收), 优惠=应退-实退
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-费率打折!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(oriMchntSettleAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(mchntFeeReceivableRate).divide(thousand).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            residueFeeActual = residueFeeActual.min(mchntFeeReceivable);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    // discount_type= 2-固定费率 min(订单金额orderAmt*discount, (手续费优惠上限fee_discount_limit-累计优惠金额total_amt_acc)
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-固定费率!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        if (afterOrderAmt.compareTo(oriMchntSettleAmt) == 0) {
                            //本次是最后一笔退款,实退为当初实收的减已经退的
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        } else {
                            //剩余消费订单金额应收手续费
                            residueFeeActual = residueOrderAmt.multiply(discount).divide(thousand).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            residueFeeActual = residueFeeActual.min(mchntFeeReceivable);
                            //实退手续费为  消费时实收手续费-累计实退手续费-剩余消费金额应收手续费
                            refundMchntFeeActual = mchntFeeActual.subtract(alredayRefundCharge).subtract(residueFeeActual);
                            refundmchntFeeDiscount = thisTimeMchntFeeReceivable.subtract(refundMchntFeeActual);
                        }
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-优惠类型异常!", feeDiscountInfoBean.getMchntNo(), feeInputMode, discountType);
                        refundMchntFeeActual = BigDecimal.ZERO;
                        refundmchntFeeDiscount = BigDecimal.ZERO;
                        break;
                }
                break;
            default:
                rglog.info("手续费收取方式错误！");
                refundMchntFeeActual = BigDecimal.ZERO;
                refundmchntFeeDiscount = BigDecimal.ZERO;
                break;
        }

        feeDiscountInfoBean.setMchntFeeDiscount(refundmchntFeeDiscount.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        feeDiscountInfoBean.setMchntFeeActual(refundMchntFeeActual.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        feeDiscountInfoBean.setMchntFeeDiscountMcNo(oriTMTxnOrderDet.getMcNo());
        //走到这能进行回退试算的订单肯定是实时减免的
        feeDiscountInfoBean.setMchntFeeDiscountMethod(CommonConstant.ONE_COMMON_CONSTANT);
        //登记订单明细信息
        recordTxnOrderDetail(comboMchntFeeDiscountTrialRefundRequest, oriTMTxnOrderDet, feeDiscountInfoBean, relativeDataJson);

        return CommonConstant.ZERO;
    }

    /**
     * 处理商户手续费营销活动全额回退
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/4/27 09:51
     */
    private void fullyMchntFeeDiscountRefundTrial(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest,
                                                  PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, TMTxnOrder oriTMTxnOrder, TMTxnOrderDet oriTMTxnOrderDet) throws Exception {
        String instId = oriTMTxnOrder.getInstId();
        String transDate = oriTMTxnOrder.getTxnDate();
        String mchntNo = oriTMTxnOrderDet.getMchntNo();
        String traceNo = oriTMTxnOrder.getFrontSeqNum();
        //本次退款记录的,手续费优惠金额,实退手续费金额
        BigDecimal refundmchntFeeDiscount = BigDecimal.ZERO;
        BigDecimal refundMchntFeeActual = BigDecimal.ZERO;

        //获取已退货信息
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, transDate, traceNo, mchntNo);

        //关联信息
        String relativeData = oriTMTxnOrderDet.getRelativeData();
        JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

        //判断是否符合全额回退
        if (null == tmStatRefund) {
            rglog.info("商户<{}>,交易流水号<{}>-未取到退货记录，之前未有过退货订单,本次可以全额退款!", mchntNo, traceNo);
            //原手续费优惠流水中relative_data(关联信息)字段中取值
            //计算实退手续费金额 ＝ 手续费优惠时实收手续费
            refundMchntFeeActual = new BigDecimal(oriTMTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(oriTMTxnOrderDet.getSubsidy()));

            //本次优惠手续费 ＝ 应退手续费 － 实退手续费
            refundmchntFeeDiscount = new BigDecimal(feeDiscountInfoBean.getMchntFeeReceivable()).subtract(refundMchntFeeActual);

            feeDiscountInfoBean.setMchntFeeDiscount(refundmchntFeeDiscount.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
            feeDiscountInfoBean.setMchntFeeActual(refundMchntFeeActual.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
            feeDiscountInfoBean.setMchntFeeDiscountMcNo(oriTMTxnOrderDet.getMcNo());
        } else {
            rglog.error("商户<{}>,交易流水号<{}>-已有退款订单，本次不能全额退款！", mchntNo, traceNo);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        //登记订单明细信息
        recordTxnOrderDetail(comboMchntFeeDiscountTrialRefundRequest, oriTMTxnOrderDet, feeDiscountInfoBean, relativeDataJson);
    }

    /**
     * 登记订单明细表
     *
     * @param comboMchntFeeDiscountTrialRefundRequest
     * @param oriTMTxnOrderDet
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void recordTxnOrderDetail(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest, TMTxnOrderDet oriTMTxnOrderDet,
                                      PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean, JSONObject oriRelativeDataJson) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrderDet refundTmTxnOrderDet = new TMTxnOrderDet();
        // 机构编码
        refundTmTxnOrderDet.setInstId(comboMchntFeeDiscountTrialRefundRequest.getHeader().getInstId());
        // 交易日期
        refundTmTxnOrderDet.setTxnDate(comboMchntFeeDiscountTrialRefundRequest.getHeader().getTransDate());
        //前端流水号
        refundTmTxnOrderDet.setFrontSeqNum(comboMchntFeeDiscountTrialRefundRequest.getHeader().getTraceNo());
        //订单号
        refundTmTxnOrderDet.setOrderId(comboMchntFeeDiscountTrialRefundRequest.getMchntOrderId());
        //商户编号
        refundTmTxnOrderDet.setMchntNo(oriTMTxnOrderDet.getMchntNo());
        //用户编号
        refundTmTxnOrderDet.setUserId(oriTMTxnOrderDet.getUserId());
        //核对状态
        refundTmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //业务状态 00:业务处理成功
        refundTmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //营销活动类型 20:手续费减免活动
        refundTmTxnOrderDet.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //原始金额
        refundTmTxnOrderDet.setOriginalAmt(feeDiscountInfoBean.getMchntFeeReceivable());
        //营销活动编号
        refundTmTxnOrderDet.setMcNo(oriTMTxnOrderDet.getMcNo());
        //规则顺序号
        refundTmTxnOrderDet.setRuleIndex(oriTMTxnOrderDet.getRuleIndex());
        //总补贴金额
        refundTmTxnOrderDet.setSubsidy(feeDiscountInfoBean.getMchntFeeDiscount());
        //机构补贴金额
        refundTmTxnOrderDet.setBankSubsidy(feeDiscountInfoBean.getMchntFeeDiscount());
        //商户补贴金额
        refundTmTxnOrderDet.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        JSONObject relativeDataJsonTrail = new JSONObject();
        //退货订单金额
        relativeDataJsonTrail.put("orderAmt", feeDiscountInfoBean.getMchntSettleAmt());
        //退货商户应收手续费
        relativeDataJsonTrail.put("mchntFeeReceivable", feeDiscountInfoBean.getMchntFeeReceivable());

        //原手续费优惠交易订单金额
        String origOrderAmt = oriRelativeDataJson.get("orderAmt").toString();
        relativeDataJsonTrail.put("origOrderAmt", origOrderAmt);
        //原手续费优惠交易手续费金额
        String origMchntFee = oriRelativeDataJson.get("mchntFeeReceivable").toString();
        relativeDataJsonTrail.put("origMchntFee", origMchntFee);
        //原手续费优惠实际优惠交易金额
        String origDisTxAmt = oriTMTxnOrderDet.getDisTxAmt();
        relativeDataJsonTrail.put("origDisTxAmt", origDisTxAmt);

        //手续费收取方式
        Object feeInputMode = oriRelativeDataJson.get("feeInputMode");
        //商户手续费优惠类型
        String discountType = oriRelativeDataJson.get("discountType").toString();
        //优惠力度
        BigDecimal discount = new BigDecimal(oriRelativeDataJson.get("discount").toString());

        //手续费收取方式
        relativeDataJsonTrail.put("feeInputMode", feeInputMode);
        //商户手续费优惠类型
        relativeDataJsonTrail.put("discountType", discountType);
        //优惠力度
        relativeDataJsonTrail.put("discount", discount);

        String relativeData = relativeDataJsonTrail.toString();
        //关联信息
        refundTmTxnOrderDet.setRelativeData(relativeData);
        //订单预留信息
        refundTmTxnOrderDet.setOrderRemark(relativeData);
        //创建人
        refundTmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        refundTmTxnOrderDet.setCreateTime(newTimeStamp);
        //最后修改人
        refundTmTxnOrderDet.setLastOprId("");
        //修改时间
        refundTmTxnOrderDet.setUpdateTime("");
        // 备用字段1
        refundTmTxnOrderDet.setRemark1("");
        // 备用字段2
        refundTmTxnOrderDet.setRemark2("");
        // 备用字段3
        refundTmTxnOrderDet.setRemark3("");
        // 备用字段4
        refundTmTxnOrderDet.setRemark4("");
        // 备用字段5
        refundTmTxnOrderDet.setRemark5("");

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();

        rglog.error("商户<{}>,交易流水号<{}>-登记订单明细信息...", refundTmTxnOrderDet.getMchntNo(), refundTmTxnOrderDet.getFrontSeqNum());
        int returnCodeTmTxnOrderDet = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(refundTmTxnOrderDet);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrderDet) {
            rglog.error("登记订单明细信息数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}, MC_NO=<{}>",
                    refundTmTxnOrderDet.getInstId(), refundTmTxnOrderDet.getFrontSeqNum(), refundTmTxnOrderDet.getOrderId(), refundTmTxnOrderDet.getMchntNo(), oriTMTxnOrderDet.getMcNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 登记订单流水表
     *
     * @param oriTMTxnOrder
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void recordTxnOrder(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest, TMTxnOrder oriTMTxnOrder, List<PaymentReturnOrderMchntFeeDiscountInfoBean> returnFeeDiscountInfoBeanList) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrder refundTmTxnOrder = new TMTxnOrder();
        //机构编码
        refundTmTxnOrder.setInstId(comboMchntFeeDiscountTrialRefundRequest.getHeader().getInstId());
        //交易日期
        refundTmTxnOrder.setTxnDate(comboMchntFeeDiscountTrialRefundRequest.getHeader().getTransDate());
        //交易时间
        refundTmTxnOrder.setTxnTime(comboMchntFeeDiscountTrialRefundRequest.getHeader().getTransTime());
        //内部交易码
        refundTmTxnOrder.setTxnNum(comboMchntFeeDiscountTrialRefundRequest.getHeader().getTxnNum());
        //业务细分
        refundTmTxnOrder.setBizType(comboMchntFeeDiscountTrialRefundRequest.getHeader().getBizType());
        //业务产品代码
        refundTmTxnOrder.setBizProdCode(oriTMTxnOrder.getBizProdCode());
        //源系统标识
        refundTmTxnOrder.setMsgSrcId(comboMchntFeeDiscountTrialRefundRequest.getHeader().getSrcSysId());
        //前端流水号
        refundTmTxnOrder.setFrontSeqNum(comboMchntFeeDiscountTrialRefundRequest.getHeader().getTraceNo());
        //订单号
        refundTmTxnOrder.setOrderId(comboMchntFeeDiscountTrialRefundRequest.getMchntOrderId());
        //商户编号
        refundTmTxnOrder.setMchntNo(oriTMTxnOrder.getMchntNo());
        //用户编号
        refundTmTxnOrder.setUserId(oriTMTxnOrder.getUserId());
        //订单金额
        refundTmTxnOrder.setOrderAmt(MompAmountUtil.getTwoDecimal(comboMchntFeeDiscountTrialRefundRequest.getReturnAmt()));

        BigDecimal txnAmt = BigDecimal.ZERO;
        BigDecimal subsidyAmt = BigDecimal.ZERO;
        for (PaymentReturnOrderMchntFeeDiscountInfoBean paymentReturnOrderMchntFeeDiscountInfoBean : returnFeeDiscountInfoBeanList) {
            txnAmt = txnAmt.add(new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeActual()));
            subsidyAmt = subsidyAmt.add(new BigDecimal(paymentReturnOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount()));
        }

        //实际支付金额——实退手续费金额
        refundTmTxnOrder.setTxnAmt(txnAmt.toString());
        //总补贴金额——总手续费优惠金额
        refundTmTxnOrder.setSubsidyAmt(MompAmountUtil.getTwoDecimal(subsidyAmt.toString()));
        //机构补贴金额
        refundTmTxnOrder.setBankSubsidyAmt(MompAmountUtil.getTwoDecimal(subsidyAmt.toString()));
        //商户补贴金额
        refundTmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //交易状态 0:成功
        refundTmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        //业务状态 01：业务处理成功
        refundTmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //批量对账状态 0：未对账
        refundTmTxnOrder.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //订单预留信息
        refundTmTxnOrder.setOrderRemark("");
        //原交易日期
        refundTmTxnOrder.setOrigTxnDate(oriTMTxnOrder.getTxnDate());
        //原交易流水号
        refundTmTxnOrder.setOrigSysSeqNum(oriTMTxnOrder.getFrontSeqNum());
        //原交易订单号
        refundTmTxnOrder.setOrigOrderId(oriTMTxnOrder.getOrderId());
        //创建人
        refundTmTxnOrder.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        refundTmTxnOrder.setCreateTime(newTimeStamp);
        //最后修改人
        refundTmTxnOrder.setLastOprId("");
        //修改时间
        refundTmTxnOrder.setUpdateTime("");
        // 备用字段1
        refundTmTxnOrder.setRemark1("");
        // 备用字段2
        refundTmTxnOrder.setRemark2("");
        // 备用字段3
        refundTmTxnOrder.setRemark3("");
        // 备用字段4
        refundTmTxnOrder.setRemark4("");
        // 备用字段5
        refundTmTxnOrder.setRemark5("");

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        rglog.error("机构<{}>,交易流水号<{}>-登记订单流水信息...", refundTmTxnOrder.getInstId(), refundTmTxnOrder.getFrontSeqNum());
        int returnCodeTmTxnOrder = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(refundTmTxnOrder);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("登记订单流水信息失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>",
                    refundTmTxnOrder.getInstId(), refundTmTxnOrder.getFrontSeqNum(), refundTmTxnOrder.getOrderId());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 请求报文检查
     *
     * @param comboMchntFeeDiscountTrialRefundRequest
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private void checkRequestMessage(ComboMchntFeeDiscountTrialRefundRequest comboMchntFeeDiscountTrialRefundRequest) throws BizException {
        // 检查上传字段 不能为负数
        /*交易金额	transAmt*/
        if (!StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getTransAmt()) && new BigDecimal(comboMchntFeeDiscountTrialRefundRequest.getTransAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 退货金额	returnAmt*/
        if (!StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getReturnAmt()) && new BigDecimal(comboMchntFeeDiscountTrialRefundRequest.getReturnAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getOrigTxnDate())) {
            rglog.error("原交易日期为空,需要上送原交易日期 !");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getOrigTraceNo())) {
            rglog.error("原交易流水号为空,需要上送原交易流水号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getMchntOrderId())) {
            rglog.error("商户订单号为空,需要上送商户订单号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getReturnAmt())) {
            rglog.error("退货金额为空,需要上送退货金额!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountTrialRefundRequest.getTransAmt())) {
            rglog.error("交易金额为空,需要上送交易金额!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (null == comboMchntFeeDiscountTrialRefundRequest.getFeeReturnOrderList() || comboMchntFeeDiscountTrialRefundRequest.getFeeReturnOrderList().isEmpty()) {
            rglog.error("手续费退款订单明细为空,需上送手续费退款订单明细!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
    }

    /**
     * 检查 订单明细上送字段 不能为负数
     *
     * @param feeDiscountInfoBean
     * @author ls
     * date 2020/10/21
     */
    private void checkFeeReturnOrderFieldHasNegativeNumber(PaymentReturnOrderMchntFeeDiscountInfoBean feeDiscountInfoBean) {

        /*  退货订单金额	orderAmt*/
        if (!StringUtil.isNullorEmpty(feeDiscountInfoBean.getOrderAmt()) && new BigDecimal(feeDiscountInfoBean.getOrderAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*商户退货清算金额	mchntSettleAmt*/
        if (!StringUtil.isNullorEmpty(feeDiscountInfoBean.getMchntSettleAmt()) && new BigDecimal(feeDiscountInfoBean.getMchntSettleAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*退货商户应收手续费金额	mchntFeeReceivable*/
        if (!StringUtil.isNullorEmpty(feeDiscountInfoBean.getMchntFeeReceivable()) && new BigDecimal(feeDiscountInfoBean.getMchntFeeReceivable()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*手续费优惠金额	mchntFeeDiscount*/
        if (!StringUtil.isNullorEmpty(feeDiscountInfoBean.getMchntFeeDiscount()) && new BigDecimal(feeDiscountInfoBean.getMchntFeeDiscount()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 实收手续费金额	mchntFeeActual*/
        if (!StringUtil.isNullorEmpty(feeDiscountInfoBean.getMchntFeeActual()) && new BigDecimal(feeDiscountInfoBean.getMchntFeeActual()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }

    }
}
